/*
 * Level.cpp
 *
 */

#include "Level.h"
#include "Model3D.h"
#include "ObjModel.h"

#include <cmath>
#include <ctime>
#include <gl/gl.h>
#include <gl/glu.h>
#include <iostream>

#define EPSILON 1.0e-6
#define NEPSILON -1.0e-6

Level::Level(int cols, int rows)
{
	if (cols%2 == 1) 	cols += 2;
	else 				cols += 3;

	if (rows%2 == 1)	rows += 2;
	else				rows += 3;

	this->cols = cols;
	this->rows = rows;

	model.make(cols, rows);

	Face face [4];
	Face boxFace;
	Vertex up(0.0f, 0.0f, 0.8f);
	Vertex n;
	Vertex2D up2d(0.0f, 0.51f);
	Vertex2D right2d(0.51f, 0.0f);

	int box;

	srand(time(NULL));

	for (int i = 0; i < cols; i++) {
		for (int j = 0; j < rows; j++) {
			model[i][j].x = i;
			model[i][j].y = j;
			model[i][j].z = levelGenFunc(i,j);

			model[i][j].geometry = new std::vector<Face>;
			model[i][j].v_geometry = new std::vector<Face>;
			model[i][j].v_geometry->reserve(24);

			model[i][j].box_Normals = NULL;
			model[i][j].box_Vertices = NULL;
			model[i][j].box_Texcoord = NULL;
			model[i][j].model3d[0] = NULL;
			model[i][j].model3d[1] = NULL;
			model[i][j].model3d[2] = NULL;

			model[i][j].bonus_type = 0;	//init bonus_type

			model[i][j].timeout = 0.0f;
			model[i][j].blowing_up = false;

			box = NO_BOX;

			/* non-breakable box */
			if (((i%2 == 0) && (j%2 == 0)) || (i == 0) || (j == 0) || (i == cols-1) || (j == rows-1)) {
				box = LEVEL_BOX;
			}
			/* breakable box TODO - clear starting locations */
			else if ((rand()/float(RAND_MAX)) < 0.2) {
				if (((i == 1) && ((j == 1) || (j == 2) || (j == rows-2) || (j == rows-3)))
						|| ((i == cols-2) && ((j == 1) || (j == 2) || (j == rows-2) || (j == rows-3)))
						|| ((i == 2) && ((j == 1) || (j == rows-2)))
						|| ((i == cols-3) && ((j == 1) || (j == rows-2)))) {
					/* Corner must be free */
				}
				else {
					box = BREAK_BOX;
					model[i][j].box_Normals = new std::vector<Vertex>;
					model[i][j].box_Vertices = new std::vector<Vertex>;
					model[i][j].box_Texcoord = new std::vector<Vertex2D>;
				}
			}

			model[i][j].box = box;

			/* Level generation - four triangles in a quad */

			/* X and Y for every vertex in each of the for faces per bounding box */
			face[0].v1.x = float(i);
			face[0].v1.y = float(j);
			face[0].v2.x = float(i+1);
			face[0].v2.y = float(j);
			face[0].v3.x = float(i)+0.5f;
			face[0].v3.y = float(j)+0.5f;
			face[0].tex1.set(0.01f, 0.01f);
			face[0].tex2.set(0.49f, 0.01f);
			face[0].tex3.set(0.25f, 0.25f);

			face[1].v1 = face[0].v2;
			face[1].v2.x = i+1;
			face[1].v2.y = j+1;
			face[1].v3 = face[0].v3;
			face[1].tex1 = face[0].tex2;
			face[1].tex2.set(0.49f, 0.49f);
			face[1].tex3 = face[0].tex3;

			face[2].v1 = face[1].v2;
			face[2].v2.x = i;
			face[2].v2.y = j+1;
			face[2].v3 = face[0].v3;
			face[2].tex1 = face[1].tex2;
			face[2].tex2.set(0.01f, 0.49f);
			face[2].tex3 = face[0].tex3;

			face[3].v1 = face[2].v2;
			face[3].v2.x = i;
			face[3].v2.y = j;
			face[3].v3 = face[0].v3;
			face[3].tex1 = face[2].tex2;
			face[3].tex2.set(0.0f, 0.01f);
			face[3].tex3 = face[0].tex3;


			/* Z coordinate for every vertex, normal and d for every face, put faces in
			 * geometry and array for drawing */
			for (int k = 0; k < 4; k++) {
				face[k].v1.z = levelGenFunc(face[k].v1.x, face[k].v1.y);
				face[k].v2.z = levelGenFunc(face[k].v2.x, face[k].v2.y);
				face[k].v3.z = levelGenFunc(face[k].v3.x, face[k].v3.y);

				face[k].n = Vertex::normal(face[k].v1, face[k].v2, face[k].v3);
				face[k].d = face[k].n^face[k].v1;

				/* Push to geometry for floor collision detection */
				model[i][j].geometry->push_back(face[k]);

				/* Update texture coords and height */
				if (box == BREAK_BOX) {
					m_Vertices.push_back(face[k].v1);
					m_Vertices.push_back(face[k].v2);
					m_Vertices.push_back(face[k].v3);
					m_Normals.push_back(face[k].n);
					m_Normals.push_back(face[k].n);
					m_Normals.push_back(face[k].n);
					m_Texcoord.push_back(face[k].tex1);
					m_Texcoord.push_back(face[k].tex2);
					m_Texcoord.push_back(face[k].tex3);
				}
				if (box) {
					face[k].v1 = face[k].v1 + up;
					face[k].v2 = face[k].v2 + up;
					face[k].v3 = face[k].v3 + up;
					face[k].tex1 = face[k].tex1 + up2d;
					face[k].tex2 = face[k].tex2 + up2d;
					face[k].tex3 = face[k].tex3 + up2d;
				}

				if (box == BREAK_BOX) {
					face[k].tex1 = face[k].tex1 + right2d;
					face[k].tex2 = face[k].tex2 + right2d;
					face[k].tex3 = face[k].tex3 + right2d;
				}

			}

			/* If  box, average the four normals, so the top looks like one quad */
			if (box) {
				n = (face[0].n + face[1].n + face[2].n + face[3].n)*(1.0f/4.0f);
				for (int k = 0; k < 4; k++) {
					face[k].n = n;
				}
			}

			/* Drawing */
			if (box == BREAK_BOX) {
				for (int k = 0; k < 4; k++) {
					model[i][j].box_Vertices->push_back(face[k].v1);
					model[i][j].box_Vertices->push_back(face[k].v2);
					model[i][j].box_Vertices->push_back(face[k].v3);
					model[i][j].box_Normals->push_back(face[k].n);
					model[i][j].box_Normals->push_back(face[k].n);
					model[i][j].box_Normals->push_back(face[k].n);
					model[i][j].box_Texcoord->push_back(face[k].tex1);
					model[i][j].box_Texcoord->push_back(face[k].tex2);
					model[i][j].box_Texcoord->push_back(face[k].tex3);
				}
			}
			else {
				for (int k = 0; k < 4; k++) {
					m_Vertices.push_back(face[k].v1);
					m_Vertices.push_back(face[k].v2);
					m_Vertices.push_back(face[k].v3);
					m_Normals.push_back(face[k].n);
					m_Normals.push_back(face[k].n);
					m_Normals.push_back(face[k].n);
					m_Texcoord.push_back(face[k].tex1);
					m_Texcoord.push_back(face[k].tex2);
					m_Texcoord.push_back(face[k].tex3);
				}
			}

			/* Box faces, make two triangles from every face of the 'floor/top' */
			if (box) {
				for (int k = 0; k < 4; k++) {
					face[k].v3 = face[k].v2;
					face[k].v2 = face[k].v1 - up;
					face[k].n = Vertex::normal(face[k].v1, face[k].v2, face[k].v3);
					face[k].d = face[k].n^face[k].v1;
					face[k].tex1.set(0.0f, 1.0f);
					face[k].tex2.set(0.0f, 0.5f);
					face[k].tex3.set(0.5f, 1.0f);
					if (box == BREAK_BOX) {
						face[k].tex1 = face[k].tex1 + right2d;
						face[k].tex2 = face[k].tex2 + right2d;
						face[k].tex3 = face[k].tex3 + right2d;
					}

					/* Push for drawing */
					if (box == BREAK_BOX) {
						model[i][j].box_Vertices->push_back(face[k].v1);
						model[i][j].box_Vertices->push_back(face[k].v2);
						model[i][j].box_Vertices->push_back(face[k].v3);
						model[i][j].box_Normals->push_back(face[k].n);
						model[i][j].box_Normals->push_back(face[k].n);
						model[i][j].box_Normals->push_back(face[k].n);
						model[i][j].box_Texcoord->push_back(face[k].tex1);
						model[i][j].box_Texcoord->push_back(face[k].tex2);
						model[i][j].box_Texcoord->push_back(face[k].tex3);
					}
					else {
						m_Vertices.push_back(face[k].v1);
						m_Vertices.push_back(face[k].v2);
						m_Vertices.push_back(face[k].v3);
						m_Normals.push_back(face[k].n);
						m_Normals.push_back(face[k].n);
						m_Normals.push_back(face[k].n);
						m_Texcoord.push_back(face[k].tex1);
						m_Texcoord.push_back(face[k].tex2);
						m_Texcoord.push_back(face[k].tex3);
					}
					/* Push to vertical geometry for wall collision detection */
					model[i][j].v_geometry->push_back(face[k]);


					face[k].v1 = face[k].v2;
					face[k].v2 = face[k].v3 - up;
					face[k].n = Vertex::normal(face[k].v1, face[k].v2, face[k].v3);
					face[k].d = face[k].n^face[k].v1;
					face[k].tex1.set(0.0f, 0.5f);
					face[k].tex2.set(0.5f, 0.5f);
					face[k].tex3.set(0.5f, 1.0f);
					if (box == BREAK_BOX) {
						face[k].tex1 = face[k].tex1 + right2d;
						face[k].tex2 = face[k].tex2 + right2d;
						face[k].tex3 = face[k].tex3 + right2d;
					}

					if (box == BREAK_BOX) {
						model[i][j].box_Vertices->push_back(face[k].v1);
						model[i][j].box_Vertices->push_back(face[k].v2);
						model[i][j].box_Vertices->push_back(face[k].v3);
						model[i][j].box_Normals->push_back(face[k].n);
						model[i][j].box_Normals->push_back(face[k].n);
						model[i][j].box_Normals->push_back(face[k].n);
						model[i][j].box_Texcoord->push_back(face[k].tex1);
						model[i][j].box_Texcoord->push_back(face[k].tex2);
						model[i][j].box_Texcoord->push_back(face[k].tex3);
					}
					else {
						m_Vertices.push_back(face[k].v1);
						m_Vertices.push_back(face[k].v2);
						m_Vertices.push_back(face[k].v3);
						m_Normals.push_back(face[k].n);
						m_Normals.push_back(face[k].n);
						m_Normals.push_back(face[k].n);
						m_Texcoord.push_back(face[k].tex1);
						m_Texcoord.push_back(face[k].tex2);
						m_Texcoord.push_back(face[k].tex3);
					}
					model[i][j].v_geometry->push_back(face[k]);
				}
			}
		}
	}

	texture = new GLuint[1];
}

Level::~Level()
{
	// TODO Auto-generated destructor stub
	// TODO delete  Vectors
	for (int i = 0; i < cols; i++) {
		for (int j = 0; j < rows; j++) {
			delete model[i][j].geometry;
			delete model[i][j].v_geometry;
			delete model[i][j].box_Normals;
			delete model[i][j].box_Vertices;
			delete model[i][j].box_Texcoord;

			delete [] texture;
		}
	}

	m_Vertices.clear();
	m_Normals.clear();
	m_Texcoord.clear();
}

void Level::initializeGL()
{
	Model3D::buildTexture("data/level03.bmp", texture[0]);
}

/* If we want to generate terrain, wee specify the function for z here */
float Level::levelGenFunc(float x, float y)
{
	return (sin(float(x)/2) + sin(float(y)/2))/1.5f;
	//return 0.0f;
}

void Level::destroyBox(int x, int y) {
	if ((x > 0) && (y > 0) && (x < cols) && (y < rows)) {
		if (model[x][y].box == BREAK_BOX) {
			model[x][y].box = NO_BOX;

			model[x][y].blowing_up = true;
			model[x][y].timeout = 500.0f;

//			delete model[x][y].box_Normals;
//			model[x][y].box_Normals = NULL;
//			delete model[x][y].box_Vertices;
//			model[x][y].box_Vertices = NULL;
//			delete model[x][y].box_Texcoord;
//			model[x][y].box_Texcoord = NULL;

			model[x][y].v_geometry->clear();

			generateBonus(model[x][y].bonus_type);
		}
	}
}

void Level::update(float milis) {
	for (int i = 0; i < cols; i++) {
		for (int j = 0; j < rows; j++) {
			if (model[i][j].box_Vertices != NULL) {
				if (model[i][j].blowing_up) {
					model[i][j].timeout -= milis;
					if (model[i][j].timeout < 0.0f) {
						model[i][j].blowing_up = false;

						delete model[i][j].box_Normals;
						model[i][j].box_Normals = NULL;
						delete model[i][j].box_Vertices;
						model[i][j].box_Vertices = NULL;
						delete model[i][j].box_Texcoord;
						model[i][j].box_Texcoord = NULL;
					}
				}
			}
		}
	}
}

/*generate bonus id for a location*/
void Level::generateBonus(int &bonus){
	bonus = rand()%2;
	if(bonus>0)
		bonus = rand()%4+1;
}


void Level::render3D()
{
	/* If we specify the pointer to array of vertices,
	 * we can draw with only a few function calls */
	//glColor3f(0.0f, 0.0f, 1.0f);
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, texture[0]);

	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	glVertexPointer(3, GL_FLOAT, 0, &m_Vertices[0]);
	glNormalPointer(GL_FLOAT, 0, &m_Normals[0]);
	glTexCoordPointer(2, GL_FLOAT, 0, &m_Texcoord[0]);

	glDrawArrays(GL_TRIANGLES, 0, m_Vertices.size());

	for (int i = 0; i < cols; i++) {
		for (int j = 0; j < rows; j++) {
			if (model[i][j].box_Vertices != NULL) {
				if (model[i][j].blowing_up) {
					glPushMatrix();
					glTranslatef(0.0f,0.0f,-1.0f + model[i][j].timeout/500);
					glTranslatef(i,j,0.0f);
					glScalef(model[i][j].timeout/500.0f, model[i][j].timeout/500.0f, model[i][j].timeout/500.0f);
					glTranslatef(-i,-j,0.0f);

				}

				glVertexPointer(3, GL_FLOAT, 0, &(model[i][j].box_Vertices->at(0)));
				glNormalPointer(GL_FLOAT, 0, &(model[i][j].box_Normals->at(0)));
				glTexCoordPointer(2, GL_FLOAT, 0, &(model[i][j].box_Texcoord->at(0)));
				glDrawArrays(GL_TRIANGLES, 0, model[i][j].box_Vertices->size());

				if (model[i][j].blowing_up) {
					glPopMatrix();
				}

			}
		}
	}

	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_NORMAL_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisable(GL_TEXTURE_2D);

	glBindTexture(GL_TEXTURE_2D, 0);

}

void Level::heightCorrection(Vertex &pos)
{
	int x_i = int(floor(pos.x));
	int y_i = int(floor(pos.y));

	float dot1, dot3, t;
	Vertex dir(0.0f, 0.0f, -1.0f);
	Vertex inter, tmp, ntmp;
	Face face;
	float t_min = 1000.0f;
	Vertex inter_min;

	/* Every face */
	for (int f = (model[x_i][y_i].geometry->size())-1; f >= 0; f--) {
		face = model[x_i][y_i].geometry->at(f);

		dot1 = face.d - (face.n^pos);
		dot3 = (face.n^dir);

		/* Parameter for ray (x = p + t*dir)*/
		t = dot1/dot3;

		/* Not the closest so far */
		if (std::abs(t) > t_min)
			continue;

		/* This is our intersection point, is it inside the triangle? */
		inter = pos + dir*t;

		tmp = inter + face.n;
		ntmp = Vertex::normal(tmp, face.v2, face.v1);
		if ((ntmp^(inter-tmp)) < 0.0f)
			continue;
		ntmp = Vertex::normal(tmp, face.v3, face.v2);
		if ((ntmp^(inter-tmp)) < 0.0f)
			continue;
		ntmp = Vertex::normal(tmp, face.v1, face.v3);
		if ((ntmp^(inter-tmp)) < 0.0f)
			continue;

		t_min = t;
		inter_min = inter;
	}

	/* If there was a collision */
	if (t_min < 900.0f) {
		pos = inter_min;
		pos.z += 0.02f;
	}
}

void Level::move(Vertex &posV, Vertex &destV, float r, float milis)
{
	int x_i;
	int y_i;

	float dot1, dot2, dot3, t;
	Vertex dir, inter, tmp, ntmp;
	Face face;
	Face *colFace = NULL;
	float t_min;
	int v_min;
	Vertex inter_min;

	/* Model3d collision */
	Vertex obj_pos;
	Face obj_face;
	float obj_r;

	// TODO (level limits)
	x_i = int(floor(destV.x));
	y_i = int(floor(destV.y));
	if ((x_i<0) || (y_i<0))
		return;

	t_min = 1000;

	/* Calculate location boxes */
	int locations[4][2];
	locations[0][0] = int(floor(posV.x));
	locations[0][1] = int(floor(posV.y));
	locations[1][1] = locations[0][1];
	locations[2][0] = locations[0][0];

	float xf = posV.x - floor(posV.x);
	float yf = posV.y - floor(posV.y);

	/* Left or right */
	if (xf < 0.5f)
		locations[1][0] = locations[0][0] - 1;

	else
		locations[1][0] = locations[0][0] + 1;
	/* Diagonal */
	locations[3][0] = locations[1][0];

	/* Up or down */
	if (yf < 0.5)
		locations[2][1] = locations[0][1] - 1;
	else
		locations[2][1] = locations[0][1] + 1;
	/* Diagonal */
	locations[3][1] = locations[2][1];

	/* Model3d collision */
	for (int i = 0; i < 4; i++) {
		x_i = locations[i][0];
		y_i = locations[i][1];

		for (int j = 0; j < 3; j++) {
			if (model[x_i][y_i].model3d[j] != NULL) {
				obj_pos = model[x_i][y_i].model3d[j]->getPosition();
				obj_r = model[x_i][y_i].model3d[j]->getDiameter();
				addGeometry(x_i, y_i, obj_pos, obj_r);
			}
		}
	}

	Vertex pos, dest;

	/* Number of jumps */
	for (int k = 1; k < 3; k++) {
		dir = destV - posV;
		/* Max 4 location boxes */
		for (int l = 0; l < 4; l++) {
			x_i = locations[l][0];
			y_i = locations[l][1];

			/* Every box face */
			for (int f = (model[x_i][y_i].v_geometry->size())-1; f >= 0; f--) {
				face = model[x_i][y_i].v_geometry->at(f);
				/* Four vertices for AA bounding box */
				for (int v = 0; v < 4; v++) {
					pos = posV;
					dest = destV;
					if (v == 0) {
						pos.x += r;
						pos.y += r;
						dest.x += r;
						dest.y += r;
					}
					else if (v == 1) {
						pos.x += r;
						pos.y -= r;
						dest.x += r;
						dest.y -= r;
					}
					else if (v == 2) {
						pos.x -= r;
						pos.y -= r;
						dest.x -= r;
						dest.y -= r;
					}
					else {
						pos.x -= r;
						pos.y += r;
						dest.x -= r;
						dest.y += r;
					}


					/* Source behind the plane */
					dot1 = face.d - (face.n^pos);
					if (dot1 > 0.0f) {
						//std::cout << "source behind "<< x_i << " "<< y_i<<  std::endl;
						continue;
					}

					/* Destination in front of the plane */
					dot2 = face.d - (face.n^dest);
					if (dot2 < 0.0f) {
						//std::cout << "destination in front "<< x_i << " "<< y_i<<  std::endl;
						continue;
					}

					dot3 = (face.n^dir);

					/* Move along the plane */
					if ((dot3 < EPSILON) && (dot3 > NEPSILON)) {
						//std::cout << "along the plane"<< std::endl;
						continue;
					}

					/* Parameter for ray (x = p + t*dir)*/
					t = dot1/dot3;

					/* Not the closest so far */
					if ((t < EPSILON) || (t > t_min))
						continue;

					/* This is our intersection point, is it inside the triangle? */
					inter = pos + dir*t + face.n*0.001f;
					heightCorrection(inter);

					tmp = inter + face.n;
					ntmp = Vertex::normal(tmp, face.v2, face.v1);
					if ((ntmp^(inter-tmp)) < 0.0f)
						continue;
					ntmp = Vertex::normal(tmp, face.v3, face.v2);
					if ((ntmp^(inter-tmp)) < 0.0f)
						continue;
					ntmp = Vertex::normal(tmp, face.v1, face.v3);
					if ((ntmp^(inter-tmp)) < 0.0f)
						continue;

					t_min = t;
					v_min = v;
					inter_min = inter;
					colFace = &model[x_i][y_i].v_geometry->at(f);
				}
			}
		}

		/* If there was a collision */
		if (colFace != NULL) {
			if (k == 2) {
				//TODO dest = inter?
				destV = posV;
				//destV = inter_min
			}
			else {
				//std::cout << "Collision"<< std::endl;
				face = *colFace;

				/* Move to intersect */
				posV = inter_min + face.n*0.01f;//r;
				//colFace = NULL;
				//posV = inter + face.n*(r+0.01f);

				/* Project destination on the collided plane */
				destV = destV - face.n*((destV-face.v1)^face.n) + face.n*0.01f;
				destV.z = posV.z;
				//destV = destV - face.n*((destV-face.v1)^face.n) + face.n*(r+0.01f);

				if (v_min == 0) {
					posV.x -= r;
					posV.y -= r;
					destV.x -= r;
					destV.y -= r;
				}
				else if (v_min == 1) {
					posV.x -= r;
					posV.y += r;
					destV.x -= r;
					destV.y += r;
				}
				else if (v_min == 2) {
					posV.x += r;
					posV.y += r;
					destV.x += r;
					destV.y += r;
				}
				else if (v_min == 3) {
					posV.x += r;
					posV.y -= r;
					destV.x += r;
					destV.y -= r;
				}
			}
		}
	}
	/* Model3d collision */
	for (int i = 0; i < 4; i++) {
		x_i = locations[i][0];
		y_i = locations[i][1];

		for (int j = 0; j < 3; j++) {
			if (model[x_i][y_i].model3d[j] != NULL) {
				removeGeometry(x_i, y_i);
			}
		}
	}
	heightCorrection(destV);
}

void Level::addGeometry(int x, int y, Vertex pos, float r) {
	Face f;
	Vertex dx(r,0,0);
	Vertex dy(0,r,0);
	Vertex dz(0,0,1);
	Vertex zero(0,0,0);

	f.v1 = pos - dx - dy - dz;
	f.v2 = pos + dx - dy - dz;
	f.v3 = pos - dx - dy + dz;
	f.n = Vertex::normal(f.v1, f.v2, f.v3);
	f.d = f.n^f.v1;
	model[x][y].v_geometry->push_back(f);
	f.v1 = f.v2;
	f.v2 = pos + dx - dy + dz;
	f.n = Vertex::normal(f.v1, f.v2, f.v3);
	f.d = f.n^f.v1;
	model[x][y].v_geometry->push_back(f);

	f.v3 = f.v2;
	f.v2 = pos + dx + dy - dz;
	f.n = Vertex::normal(f.v1, f.v2, f.v3);
	f.d = f.n^f.v1;
	model[x][y].v_geometry->push_back(f);
	f.v1 = f.v2;
	f.v2 = pos + dx + dy + dz;
	f.n = Vertex::normal(f.v1, f.v2, f.v3);
	f.d = f.n^f.v1;
	model[x][y].v_geometry->push_back(f);

	f.v3 = f.v2;
	f.v2 = pos - dx + dy - dz;
	f.n = Vertex::normal(f.v1, f.v2, f.v3);
	f.d = f.n^f.v1;
	model[x][y].v_geometry->push_back(f);
	f.v1 = f.v2;
	f.v2 = pos - dx + dy + dz;
	f.n = Vertex::normal(f.v1, f.v2, f.v3);
	f.d = f.n^f.v1;
	model[x][y].v_geometry->push_back(f);

	f.v3 = f.v2;
	f.v2 = pos - dx - dy - dz;
	f.n = Vertex::normal(f.v1, f.v2, f.v3);
	f.d = f.n^f.v1;
	model[x][y].v_geometry->push_back(f);
	f.v1 = f.v2;
	f.v2 = pos - dx - dy + dz;
	f.n = Vertex::normal(f.v1, f.v2, f.v3);
	f.d = f.n^f.v1;
	model[x][y].v_geometry->push_back(f);

}

void Level::removeGeometry(int x, int y) {
	for (int i = 0; i < 8; i++) {
		model[x][y].v_geometry->pop_back();
	}
}
